package maskedpixel.ogmo 
{
	import adobe.utils.CustomActions;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.FileFilter;
	import flash.net.FileReference;
	import flash.utils.ByteArray;
	import maskedpixel.ogmo.*;
	import maskedpixel.ogmo.utils.*;
	/**
	 * ...
	 * @author Erin M Gunn
	 */
	public class OgmoProject
	{
		/**
		 * Override this function to register everything needed in the ogmo project.
		 * This is here more to promote consistency and cleanliness, but pretend I didn't say that.
		 */
		public function registration():void
		{
			
		}
		
		// ---- Everything Static ----
		
		/**
		 * Stores the registered Ogmo Settings names.
		 */
		public static var ogmoSettingNames:Vector.<String> = new Vector.<String>();
		
		/**
		 * Stores the registered Ogmo Settings values.
		 */
		public static var ogmoSettingValues:Vector.<String> = new Vector.<String>();
		
		/**
		 * Stores the registered OgmoLayers.
		 */
		public static var ogmoLayers:Vector.<OgmoLayer> = new Vector.<OgmoLayer>();
		
		/**
		 * Stores the registered OgmoTileSets.
		 */
		public static var ogmoTileSets:Vector.<OgmoTileSet> = new Vector.<OgmoTileSet>();
		
		/**
		 * Stores the registered OgmoValues.
		 */
		public static var ogmoValues:Vector.<OgmoValue> = new Vector.<OgmoValue>();
		
		/**
		 * Stores the registered OgmoFolders.
		 */
		public static var ogmoFolders:Vector.<OgmoFolder> = new Vector.<OgmoFolder>();
		
		/**
		 * Stores the registered OgmoObjects.
		 */
		public static var ogmoObjects:Vector.<OgmoObject> = new Vector.<OgmoObject>();
		
		/**
		 * The name of the project.
		 */
		public static var projectName:String = "OgmoProject";
		
		/**
		 * Generates the ogmo project file.
		 */
		public static function generateProject():void
		{
			fileRef = new FileReference();
			fileRef.addEventListener(Event.SELECT, onSaveFileSelected);
			fileRef.addEventListener(Event.CANCEL, onCancel);
			fileRef.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
			fileRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
			fileRef.save(OgmoProject.generateXML(), projectName + ".oep");
		}
		
		
		/**
		 * Resets all stativ variables to their default values.
		 */
		public static function clearProject():void
		{
			ogmoSettingNames.length = 0;
			ogmoSettingValues.length = 0;
			ogmoLayers.length = 0;
			ogmoTileSets.length = 0;
			ogmoValues.length = 0;
			ogmoFolders.length = 0;
			ogmoObjects.length = 0;
			
			projectName = "OgmoProjects";
		}
		
		/**
		 * Register any of the project settings.
		 * @param	name	Name of the setting.
		 * @param	value	Value of the setting.
		 */
		public static function registerSetting(name:String, value:String):void
		{
			ogmoSettingNames.push(name);
			ogmoSettingValues.push(value);
		}
		
		/**
		 * Register a new layer with the ogmo project.
		 * @param	layer	The layer to register.
		 */
		public static function registerLayer(...layers):void
		{
			for each(var layer:Object in layers)
			{
				if(layer is OgmoLayer)
				{
					if (ogmoLayers.indexOf(layer) == -1)
					{
						ogmoLayers.push(layer);
					}
				}
				if(layer is Vector.<OgmoLayer> || layer is Array)
				{
					for each(var lay:OgmoLayer in layer)
					{
						if (ogmoLayers.indexOf(lay) == -1)
						{
							ogmoLayers.push(lay);
						}
					}
				}
			}
		}
		
		/**
		 * Register a tileSet to be used with the ogmo project.
		 * @param	tileSet	The tileset to register.
		 */
		public static function registerTileSet(...tileSets):void
		{
			for each(var tileSet:Object in tileSets)
			{
				if (tileSet is OgmoTileSet)
				{
					if (ogmoTileSets.indexOf(tileSet) == -1)
					{
						ogmoTileSets.push(tileSet);
					}
				}
				if (tileSet is Vector.<OgmoLayer> || tileSet is Array)
				{
					for each(var tiles:OgmoTileSet in tileSet)
					{
						if (ogmoTileSets.indexOf(tiles) == -1)
						{
							ogmoTileSets.push(tiles);
						}
					}
				}
			}
		}
		
		/**
		 * Register a folder to be used with the ogmo project.
		 * @param	folder	The folder to register.
		 */
		public static function registerFolder(...folders):void
		{
			for each(var folder:Object in folders)
			{
				if (folder is OgmoFolder)
				{
					if (ogmoFolders.indexOf(folder) == -1)
					{
						ogmoFolders.push(folder);
					}
				}
				if (folder is Vector.<OgmoFolder> || folder is Array)
				{
					for each(var fold:OgmoFolder in folder)
					{
						if (ogmoFolders.indexOf(fold) == -1)
						{
							ogmoFolders.push(fold);
						}
					}
				}
			}
		}
		
		/**
		 * Registers an object to be used with the ogmo project.
		 * @param	object	The object to register.
		 */
		public static function registerObject(...objects):void
		{
			for each(var object:Object in objects)
			{
				if (object is OgmoObject)
				{
					if (ogmoObjects.indexOf(object) == -1)
					{
						ogmoObjects.push(object);
					}
				}
				if (object is Vector.<OgmoObject> || object is Array)
				{
					for each(var obj:OgmoObject in object)
					{
						if (ogmoObjects.indexOf(obj) == -1)
						{
							ogmoObjects.push(obj);
						}	
					}
				}
			}
		}
		
		/**
		 * Registers a value to be used with the ogmo project.
		 * @param	value	The value to be registered.
		 */
		public static function registerValue(...values):void
		{
			for each(var value:Object in values)
			{
				if (value is OgmoValue)
				{
					if (ogmoValues.indexOf(value) == -1)
					{
						ogmoValues.push(value);
					}
				}
				if (value is Vector.<OgmoValue> || value is Array)
				{
					for each(var val:OgmoValue in value)
					{
						if (ogmoValues.indexOf(val) == -1)
						{
							ogmoValues.push(val);
						}
					}
				}
			}
		}
		
		/**
		 * Generates the XML representing this project in an Ogmo Project file.
		 * @return
		 */
		private static function generateXML():XML 
		{
			var project:XML = <project></project>;
			project["name"] = projectName;
			
			for (var i:uint = 0; i < ogmoSettingNames.length; i++)
			{
				project.settings[ogmoSettingNames[i]] = ogmoSettingValues[i];
			}
			for (i = 0; i < ogmoValues.length; i++)
			{
				project.values.*[i] = ogmoValues[i].generateXML();
			}
			for (i = 0; i < ogmoTileSets.length; i++)
			{
				project.tilesets.*[i] = ogmoTileSets[i].generateXML();
			}
			for (i = 0; i < ogmoObjects.length; i++)
			{
				project.objects.*[i] = ogmoObjects[i].generateXML();
			}
			for (i = 0; i < ogmoFolders.length; i++)
			{
				project.objects.*[project.objects.children().length()] = ogmoFolders[i].generateXML();
			}
			for (i = 0; i < ogmoLayers.length; i++)
			{
				project.layers.*[i] = ogmoLayers[i].generateXML();
			}
			
			return project;
		}
		
		/*---- EVENT HANDLERS ---- */
		
		private static function onSecurityError(e:SecurityErrorEvent):void 
		{
			trace("There was a Security Error.");
		}
		
		private static function onIOError(e:IOErrorEvent):void 
		{
			trace("There was an IO Error.");
		}
		
		private static function onCancel(e:Event):void 
		{
			trace("The save request was cancelled by the user.");
		}
		
		private static function onSaveFileSelected(e:Event):void 
		{
			fileRef.addEventListener(ProgressEvent.PROGRESS, onSaveProgress);
			fileRef.addEventListener(Event.COMPLETE, onSaveComplete);
			fileRef.addEventListener(Event.CANCEL, onSaveCancel);
		}
		
		private static function onSaveCancel(e:Event):void 
		{
			trace("File saving was cancelled");
		}
		
		private static function onSaveComplete(e:Event):void 
		{
			trace("File saved.");
			fileRef.removeEventListener(Event.SELECT, onSaveFileSelected);
			fileRef.removeEventListener(ProgressEvent.PROGRESS, onSaveProgress);
			fileRef.removeEventListener(Event.COMPLETE, onSaveComplete);
			fileRef.removeEventListener(Event.CANCEL, onSaveCancel);
		}
		
		private static function onSaveProgress(e:ProgressEvent):void 
		{
			trace("Saved " + e.bytesLoaded + " of " + e.bytesTotal + " bytes.");
		}
		
		// Used when saving the project file in the even handlers.
		/** @private */ private static var fileRef:FileReference;
		
	}

}